<template>
  <div class="w-full">
    <div class="upload">
      <div class="upload-card">
        <!--图片列表-->
        <div class="upload-card-item" :style="getCSSProperties" v-for="(item, index) in imgList" :key="`img_${index}`">
          <div class="upload-card-item-info">
            <div class="img-box">
              <img :src="item" />
            </div>
            <div class="img-box-actions">
              <span size="18" class="mx-2 action-icon" @click="preview(item)">
                <EyeOutlined style="font-size: 18px" class="arco-icon" />
              </span>
              <span v-if="!props.disabled" size="18" class="mx-2 action-icon" @click="remove(index)">
                <DeleteOutlined class="arco-icon" />
              </span>
            </div>
          </div>
        </div>

        <!--上传图片-->
        <div class="upload-card-item upload-card-item-select-picture" :style="getCSSProperties"
          v-if="imgList.length < maxNumber && !props.disabled">
          <a-upload v-bind="bindValue" :showUploadList="false" :beforeUpload="beforeUpload" @change="change">
            <template #upload-button>
              <div class="flex flex-col justify-center w-full">
                <span size="18" class="m-auto">
                  <PlusOutlined class="arco-icon" />
                </span>
                <span class="upload-title text-center">上传图片</span>
              </div>
            </template>
          </a-upload>
        </div>
      </div>
    </div>

    <!--上传图片-->
    <a-space>
      <a-alert title="提示" type="info" v-if="helpText" class="flex w-full">
        {{ helpText }}
      </a-alert>
    </a-space>
  </div>

  <!--预览图片-->
  <previewModal ref="previewModalRef" :previewUrl="previewUrl" />
</template>

<script lang="ts" setup>
import { ref, computed, useAttrs, watch } from 'vue';
import { EyeOutlined, DeleteOutlined, PlusOutlined } from '@vicons/antd';
import { basicProps } from './props';
import { Message, Modal } from '@arco-design/web-vue';
import { ResultEnum } from '@/enums/httpEnum';
import componentSetting from '@/settings/componentSetting';
import { useGlobSetting } from '@/hooks/setting';
import { isString } from '@/utils/is';
import { omit } from 'lodash-es';
import previewModal from './PreviewModal.vue';

const globSetting = useGlobSetting();

const props = defineProps({ ...basicProps });

const attrs = useAttrs();

const emit = defineEmits(['uploadChange', 'delete', 'update:value']);

const previewModalRef = ref();

const bindValue = computed(() => {
  const value = { ...attrs, ...props };
  return omit(value, 'onChange');
});

const getCSSProperties = computed(() => {
  return {
    width: `${props.width}px`,
    height: `${props.height}px`,
  };
});

const previewUrl = ref('');
const originalImgList = ref([]);
const imgList: any = ref([]);

//赋值默认图片显示
watch(
  () => props.value,
  () => {
    if (typeof props.value === 'string') {
      if (props.value) {
        imgList.value = props.value.split(',').map((item) => {
          return getImgUrl(item);
        });
      } else {
        imgList.value = []
      }
    } else {
      imgList.value = props.value.map((item) => {
        return getImgUrl(item);
      });
    }
  },
  {
    immediate: true,
  },
);

//预览
function preview(url: string) {
  previewUrl.value = url;
  previewModalRef.value.openModal();
}

//删除
function remove(index: number) {
  Modal.open({
    title: '提示',
    content: '你确定要删除吗？',
    okText: '确认',
    cancelText: '取消',
    alignCenter: true,
    onOk() {
      imgList.value.splice(index, 1);
      originalImgList.value.splice(index, 1);
      emit('uploadChange', originalImgList.value.toString());
      emit('update:value', originalImgList.value.toString());
      emit('delete', originalImgList.value.toString());
    },
  });
}

//组装完整图片地址
function getImgUrl(url: string): string {
  const { imgUrl } = globSetting;
  return /(^http|https:\/\/)/g.test(url) ? url : `${imgUrl}${url}`;
}

function checkFileType(fileType: string) {
  return componentSetting.upload.fileType.includes(fileType);
}

//上传之前
function beforeUpload(file) {
  const fileInfo = file;
  const { maxSize, accept } = props;
  const acceptRef = (isString(accept) && accept.split(',')) || [];

  // 设置最大值，则判断
  if (maxSize && fileInfo.size / 1024 / 1024 >= maxSize) {
    Message.error(`上传文件最大值不能超过${maxSize}M`);
    return false;
  }

  // 设置类型,则判断
  const fileType = componentSetting.upload.fileType;
  if (acceptRef.length > 0 && !checkFileType(fileInfo.type)) {
    Message.error(`只能上传文件类型为${fileType.join(',')}`);
    return false;
  }

  return true;
}

//上传图片
function change(_, file) {
  if (file && file.status === 'done') {
    //完成
    try {
      const res = file.response;
      const { infoField } = componentSetting.upload.apiSetting;
      const { code } = res;
      const msg = res.msg || res.message || '上传失败';
      const result = res[infoField];
      //成功
      if (code === ResultEnum.SUCCESS) {
        let imgUrl: string = getImgUrl(result.uuid);
        imgList.value.push(imgUrl as never);
        originalImgList.value.push(result.uuid as never);
        emit('uploadChange', originalImgList.value.toString());
        emit('update:value', originalImgList.value.toString());
      } else Message.error(msg);
    } catch (error) {
      console.error(error);
    }
  }
}
</script>

<style lang="less">
.upload {
  width: 100%;
  overflow: hidden;

  &-card {
    width: auto;
    height: auto;
    display: flex;
    flex-wrap: wrap;
    align-items: center;

    &-item {
      margin: 0 8px 8px 0;
      position: relative;
      padding: 8px;
      border: 1px solid #d9d9d9;
      border-radius: 2px;
      display: flex;
      justify-content: center;
      flex-direction: column;
      align-items: center;

      &:hover {
        background: 0 0;

        .upload-card-item-info::before {
          opacity: 1;
        }

        &-info::before {
          opacity: 1;
        }
      }

      &-info {
        position: relative;
        height: 100%;
        padding: 0;
        overflow: hidden;

        &:hover {
          .img-box-actions {
            opacity: 1;
          }
        }

        &::before {
          position: absolute;
          z-index: 1;
          width: 100%;
          height: 100%;
          background-color: rgba(0, 0, 0, 0.5);
          opacity: 0;
          transition: all 0.3s;
          content: ' ';
        }

        .img-box {
          position: relative;
          //padding: 8px;
          //border: 1px solid #d9d9d9;
          border-radius: 2px;
        }

        .img-box-actions {
          position: absolute;
          top: 50%;
          left: 50%;
          z-index: 10;
          white-space: nowrap;
          transform: translate(-50%, -50%);
          opacity: 0;
          transition: all 0.3s;
          display: flex;
          align-items: center;
          justify-content: space-between;

          &:hover {
            background: 0 0;
          }

          .action-icon {
            color: rgba(255, 255, 255, 0.85);

            &:hover {
              cursor: pointer;
              color: #fff;
            }
          }
        }
      }
    }

    &-item-select-picture {
      border: 1px dashed #d9d9d9;
      border-radius: 2px;
      cursor: pointer;
      background: #fafafa;
      color: #666;

      .upload-title {
        color: #666;
      }
    }
  }
}
</style>
